#ifndef _MultiIo_H_
#define _MultiIo_H_

#include <sys/epoll.h>
#include <unistd.h>
#include <error.h>
#include "Log.hpp"
class MultiIo 
{
public:
	//构造函数
	MultiIo (void)
    {
        // 创建epoll对象，若失败
        if ((_epoll = epoll_create1(0)) == -1)
        {
            lg(Error, "socker error, %s: %d", strerror(errno), errno);  
            // 记录一般错误日志
            // g_app->m_log.printf(Log::LEVEL_ERR, __FILE__, __LINE__,
            //                     "epoll_create1: %s", strerror(errno));
        }
    }
    //析构函数
	~MultiIo (void) { close(_epoll); }

    // fd发生输入输出事件的文件描述符
    // event 事件描述结构
	bool add (int fd,epoll_event& event) const //增加需要被关注的输入输出事件
    {
        // 将文件描述符及其被关注的事件加入epoll，若失败
        if (epoll_ctl(_epoll, EPOLL_CTL_ADD, fd, &event) == -1)
        {
            // 记录警告日志
            // g_app->m_log.printf(Log::LEVEL_WAR, __FILE__, __LINE__,
            //                     "epoll_ctl: %s", strerror(errno));
            // 返回失败
            lg(Error, "socker error, %s: %d", strerror(errno), errno);
            return false;
        }

        // 返回成功
        return true;
    }

    ///< [in] 发生输入输出事件的文件描述符
    ///< [in] 事件描述结构
	bool del (int fd,epoll_event& event) const//删除事件
    {
        // 将文件描述符及其被关注的事件从epoll中删除，若失败
        if (epoll_ctl(_epoll, EPOLL_CTL_DEL, fd, &event) == -1)
        {
            // 记录警告日志
            // g_app->m_log.printf(Log::LEVEL_WAR, __FILE__, __LINE__,
            //                     "epoll_ctl: %s", strerror(errno));
            // 返回失败
            lg(Error, "socker error, %s: %d", strerror(errno), errno);
            return false;
        }

        // 返回成功
        return true;
    }
	// >0 处于就绪状态的文件描述符数
	// 0  超时
	// -1 失败
    // events 事件描述结构数组
    // max 事件描述结构数组容量
    // timeout超时毫秒数，0立即超时，-1无限超时
	int wait (epoll_event events[], int max,int timeout)const //等待所关注输入输出事件的发生
    {
        // 等待epoll中的文件描述符发生所关注的事件
        int fds = epoll_wait(_epoll, events, max, timeout);
        // 若发生除被信号中断以外的错误
        if (fds == -1 && errno != EINTR);
         {   // 记录警告日志
            // g_app->m_log.printf(Log::LEVEL_WAR, __FILE__, __LINE__,
            //                     "epoll_wait: %s", strerror(errno));
            lg(Error, "socker error, %s: %d", strerror(errno), errno);
         }
        // 返回处于就绪状态的文件描述符数，超时返回0，失败返回-1
        return fds;
    }

private:
	int _epoll; //多路输入输出对象实例句柄(文件描述符)
}; 

#endif //_MultiIo_H_